home *** CD-ROM | disk | FTP | other *** search
- /*
- ** Copyright (c) 1991 Bolt Beranek and Newman, Inc.
- ** All rights reserved.
- **
- ** Redistribution and use in source and binary forms are permitted
- ** provided that: (1) source distributions retain this entire copyright
- ** notice and comment, and (2) distributions including binaries display
- ** the following acknowledgement: ``This product includes software
- ** developed by Bolt Beranek and Newman, Inc. and CREN/CSNET'' in the
- ** documentation or other materials provided with the distribution and in
- ** all advertising materials mentioning features or use of this software.
- ** Neither the name of Bolt Beranek and Newman nor CREN/CSNET may be used
- ** to endorse or promote products derived from this software without
- ** specific prior written permission.
- **
- ** THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
- ** WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
- ** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- */
- #include <stdio.h>
- #include <ctype.h>
- #include <netdb.h>
- #include <sgtty.h>
- #include <sys/types.h>
- #include <sys/param.h>
- #include <netinet/in_systm.h>
- #include <netinet/in.h>
- #include <netinet/ip.h>
- #include <arpa/inet.h>
- #include "dialupip.h"
- #include "diald.h"
-
-
- /*
- ** Some systems don't have these in their <netinet/in.h>
- */
- #ifndef IPPROTO_EGP
- #define IPPROTO_EGP 8
- #endif /* IPPROTO_EGP */
- #ifndef IPPROTO_RDP
- #define IPPROTO_RDP 27
- #endif /* IPPROTO_EGP */
-
-
- #define EQ(a, b) (strcmp((a), (b)) == 0)
- #define nexttok() strtok((char *)NULL, SEPARATORS)
-
-
- static int errorcount;
- static int linenum;
- static char SEPARATORS[] = " \t";
- static REMOTE *RemoteTable;
- static int RemoteCount;
- static char WHERE[] = "readconfig";
-
-
- /*
- ** Find this interface in our list.
- */
- REMOTE *
- findconfig(device)
- register char *device;
- {
- register REMOTE *rp;
- register int i;
-
- for (rp = RemoteTable, i = RemoteCount; --i >= 0; rp++)
- if (strcmp(device, rp->Device) == 0)
- return rp;
- return NULL;
- }
-
-
- /*
- ** Is the host (or its network) on the list of hosts and networks?
- */
- int
- hostinlist(list, addr)
- struct in_addr *list;
- struct in_addr addr;
- {
- register int i;
- register int j;
-
- j = i = addr.s_addr % MAXHOSTS;
-
- do {
- if (list[j].s_addr == 0)
- return 0;
- if (list[j].s_addr == addr.s_addr)
- return 1;
- if (inet_lnaof(list[j].s_addr) == 0
- && inet_netof(list[j].s_addr) == inet_netof(addr.s_addr))
- return 1;
-
- if (++j == MAXHOSTS)
- j = 0;
- } while (j != i);
-
- return 0;
- }
-
-
-
- static void
- yyerror(path, fmt, arg)
- char *path;
- char *fmt;
- char *arg;
- {
- char buff[256];
-
- (void)sprintf(buff, "Error near line %d of\n\t \"%s\": %s\n",
- linenum, path, fmt);
- d_log(DLOG_GENERAL, WHERE, buff, arg);
- errorcount++;
- }
-
-
- static void
- parseprotocols(path, lp)
- char *path;
- u_long *lp;
- {
- char *p;
- int i;
-
- while (p = nexttok()) {
- if (EQ(p, "tcp"))
- i = IPPROTO_TCP;
- else if (EQ(p, "rdp"))
- i = IPPROTO_RDP;
- else if (EQ(p, "egp"))
- i = IPPROTO_EGP;
- else if (EQ(p, "icmp"))
- i = IPPROTO_ICMP;
- else if (EQ(p, "udp"))
- i = IPPROTO_UDP;
- else if (EQ(p, "ggp"))
- i = IPPROTO_GGP;
- else {
- yyerror(path, "Bad protocol \"%s\"", p);
- continue;
- }
- lp[P_WORD(i)] |= P_BIT(i);
- }
- }
-
-
- static int
- positivenumber(p)
- char *p;
- {
- if (*p == '\0')
- return 0;
- for ( ; *p; p++)
- if (!isdigit(*p))
- return 0;
- return 1;
- }
-
-
- static long
- parsetime(path)
- char *path;
- {
- long l;
- int i;
- char *p;
-
- for (l = 0; p = nexttok(); )
- if (!positivenumber(p) || (i = atoi(p)) < 0 || i > 23)
- yyerror(path, "Bad hour \"%s\"", p);
- else
- l |= (1L << i);
- return l;
- }
-
-
- static int
- addhosttolist(list, addr)
- struct in_addr *list;
- struct in_addr addr;
- {
- register int i;
- register int j;
-
- j = i = addr.s_addr % MAXHOSTS;
- do {
- if (list[j].s_addr == 0) {
- list[j] = addr;
- return 1;
- }
- if (++j == MAXHOSTS)
- j = 0;
- } while (j != i);
-
- return 0;
- }
-
-
-
- static int
- parseaddresslist(path, list)
- char *path;
- struct in_addr *list;
- {
- char *p;
- struct in_addr new;
- int i;
- struct hostent *hp;
- struct netent *np;
-
- for (i = 0; p = nexttok(); i++) {
- if ((new.s_addr = inet_addr(p)) != -1)
- ;
- else if (np = getnetbyname(p))
- new = inet_makeaddr(np->n_net, 0);
- else if (hp = gethostbyname(p))
- bcopy(hp->h_addr, (caddr_t)&new, sizeof new);
- else {
- yyerror(path, "Bad IP address \"%s\"", p);
- continue;
- }
- if (!hostinlist(list, new) && !addhosttolist(list, new))
- yyerror(path, "Can't add \"%s\" to address list", p);
- }
- return i;
- }
-
-
- static int
- readentry(path, rp, line)
- char *path;
- REMOTE *rp;
- char *line;
- {
- static char MISSINGFIELD[] = "Required \"%s\" field is missing";
- FILE *F;
- char *sitep;
- char *ttysp;
- char *scriptp;
- char *transp;
- char *accessp;
- char *word;
- char *p;
- char *fp;
- char buff[BUFSIZ];
- int i;
-
- /* Make sure we have six colon-separated fields. */
- if ((sitep = strchr(line, ':')) == NULL
- || (ttysp = strchr(sitep + 1, ':')) == NULL
- || (scriptp = strchr(ttysp + 1, ':')) == NULL
- || (transp = strchr(scriptp + 1, ':')) == NULL
- || (accessp = strchr(transp + 1, ':')) == NULL) {
- yyerror(path, "Too few fields", (char *)NULL);
- return 0;
- }
- *sitep++ = '\0';
- *ttysp++ = '\0';
- *scriptp++ = '\0';
- *transp++ = '\0';
- *accessp++ = '\0';
-
- /* Field one, the interface. */
- if (*line == '\0') {
- yyerror(path, MISSINGFIELD, "interface");
- return 0;
- }
- (void)strcpy(rp->Device, line);
-
- /* Field two, the site name. */
- if (*sitep == '\0') {
- yyerror(path, MISSINGFIELD, "site");
- return 0;
- }
- (void)strcpy(rp->Sitename, sitep);
-
- /* Field three, the tty#baudrate entries. */
- if (*ttysp == '\0' || (p = strtok(ttysp, SEPARATORS)) == NULL) {
- yyerror(path, MISSINGFIELD, "ttys");
- return 0;
- }
- for (i = 0; p && i < MAXDEVICES; i++, p = nexttok()) {
- if ((fp = strchr(p, '#')) == NULL)
- rp->Speeds[i] = -1;
- else
- *fp++ = '\0';
- (void)strcpy(rp->Lines[i], p);
- if (fp)
- switch (atoi(fp)) {
- default:
- yyerror(path, "Bad speed \"%s\"\n", fp);
- break;
- case 1200: rp->Speeds[i] = B1200; break;
- case 2400: rp->Speeds[i] = B2400; break;
- case 4800: rp->Speeds[i] = B4800; break;
- case 9600: rp->Speeds[i] = B9600; break;
- case 19200: rp->Speeds[i] = EXTA; break;
- case 38400: rp->Speeds[i] = EXTB; break;
- }
- }
- if (i >= MAXDEVICES) {
- yyerror(path, "Too many tty entries", (char *)NULL);
- return 0;
- }
- while (i < MAXDEVICES)
- rp->Lines[i++][0] = '\0';
-
- /* Field four, the script file and parameters. */
- if (*scriptp == '\0' || (p = strtok(scriptp, SEPARATORS)) == NULL) {
- yyerror(path, "Missing script name", (char *)NULL);
- return 0;
- }
- if (*p == '/')
- (void)strcpy(rp->Script, p);
- else
- (void)sprintf(rp->Script, "%s/%s", CONFIG_DIR, p);
- for (fp = rp->FieldData, i = 0; i < 10 && (p = nexttok()); i++) {
- if (fp > &rp->FieldData[sizeof rp->FieldData - 1]) {
- yyerror(path, "Parameters too long", (char *)NULL);
- break;
- }
- rp->Fields[i] = fp - rp->FieldData;
- fp += strlen(strcpy(fp, p));
- *fp++ = '\0';
- }
- if (i >= 10) {
- yyerror(path, "Too many parameters", (char *)NULL);
- return 0;
- }
- rp->FieldCount = i;
-
- /* Field five, the transcript file. */
- if ((p = strchr(transp, '@')) && isdigit(p[1]) && p[2] == '\0')
- rp->Transtyle = *++p == '0' ? TS_LOW : TS_HIGH;
- else
- rp->Transtyle = TS_LOW;
- if (*transp == '/')
- (void)strcpy(rp->Transcript, transp);
- else
- (void)sprintf(rp->Transcript, "%s/%s", CONFIG_DIR, transp);
-
- /* Set access defaults. */
- for (i = 0; i < 7; i++)
- rp->Times[i] = ~0;
- for (i = 0; i < 8; i++)
- rp->Protocols[i] = ~0;
- for (rp->AllowCount = 0, i = 0; i < MAXHOSTS; i++)
- rp->AllowTo[i].s_addr = 0;
- for (rp->DisallowCount = 0, i = 0; i < MAXHOSTS; i++)
- rp->DisallowFrom[i].s_addr = 0;
- rp->Inactivity = INACT_UNDEF;
-
- /* Field five, the access file. */
- if (*accessp == '\0')
- return errorcount == 0;
-
- if (*accessp == '/')
- (void)strcpy(buff, accessp);
- else
- (void)sprintf(buff, "%s/%s", CONFIG_DIR, accessp);
- if ((F = fopen(buff, "r")) == NULL) {
- yyerror(path, "Can't open access file \"%s\"", accessp);
- return 0;
- }
-
- /* Read lines. */
- for (linenum = 1; fgets(buff, sizeof buff, F); linenum++) {
- if ((p = strchr(buff, '\n')) == NULL) {
- yyerror(buff, "Line too long", (char *)NULL);
- (void)fclose(F);
- return 0;
- }
- *p = '\0';
- if (*p == '\0' || *p == '#')
- continue;
- if ((word = strtok(buff, SEPARATORS)) == NULL)
- continue;
- /* Dispatch on the word to fill in the fields. */
- if (EQ(word, "allowto") || EQ(word, "gooddstaddresses"))
- rp->AllowCount += parseaddresslist(path, rp->AllowTo);
- else if (EQ(word, "disallowfrom") || EQ(word, "badsrcaddresses"))
- rp->DisallowCount += parseaddresslist(path, rp->DisallowFrom);
- else if (EQ(word, "protocols"))
- parseprotocols(path, rp->Protocols);
- else if (EQ(word, "inactivity")) {
- if (p = nexttok())
- if (!positivenumber(p))
- yyerror(accessp, "Bad number \"%s\"", p);
- else
- rp->Inactivity = atoi(p);
- }
- else if (EQ(word, "weekdays"))
- rp->Times[1] = rp->Times[2] = rp->Times[3] =
- rp->Times[4] = rp->Times[5] = parsetime(path);
- else if (EQ(word, "weekends"))
- rp->Times[0] = rp->Times[6] = parsetime(path);
- else if (EQ(word, "sun") || EQ(word, "sunday"))
- rp->Times[0] = parsetime(path);
- else if (EQ(word, "mon") || EQ(word, "monday"))
- rp->Times[1] = parsetime(path);
- else if (EQ(word, "tue") || EQ(word, "tuesday"))
- rp->Times[2] = parsetime(path);
- else if (EQ(word, "wed") || EQ(word, "wednesday"))
- rp->Times[3] = parsetime(path);
- else if (EQ(word, "thu") || EQ(word, "thursday"))
- rp->Times[4] = parsetime(path);
- else if (EQ(word, "fri") || EQ(word, "friday"))
- rp->Times[5] = parsetime(path);
- else if (EQ(word, "sat") || EQ(word, "saturday"))
- rp->Times[6] = parsetime(path);
- else
- yyerror(accessp, "Bad parameter \"%s\"", word);
- }
-
- (void)fclose(F);
- return errorcount == 0;
- }
-
-
- int
- readconfig(path)
- char *path;
- {
- FILE *F;
- char *p;
- char buff[BUFSIZ];
- int i;
-
- /* Count the number of lines in the file. */
- linenum = 0;
- if ((F = fopen(path, "r")) == NULL) {
- yyerror(path, "Can't open for reading, %m", (char *)NULL);
- return 0;
- }
- while (fgets(buff, sizeof buff, F))
- if (buff[0] != '#')
- linenum++;
- rewind(F);
-
- /* Allocate space for the table. */
- if (RemoteTable)
- free((char *)RemoteTable);
- RemoteTable = (REMOTE *)malloc((unsigned int)linenum * sizeof (REMOTE));
- if (RemoteTable == NULL) {
- yyerror(path, "Can't allocate table, %m", (char *)NULL);
- return 0;
- }
-
- errorcount = 0;
- for (i = 1, RemoteCount = 0; fgets(buff, sizeof buff, F); i++) {
- if ((p = strchr(buff, '\n')) == NULL) {
- yyerror(path, "Line too long", (char *)NULL);
- (void)fclose(F);
- return 0;
- }
- *p = '\0';
- if (buff[0] == '#' || buff[0] == '\0')
- continue;
-
- linenum = i;
- if (readentry(path, &RemoteTable[RemoteCount], buff))
- RemoteCount++;
- }
-
- (void)fclose(F);
- return errorcount == 0;
- }
-